package com.liuzhilong.infrastructure.basic.file;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.util.Random;

import static com.liuzhilong.infrastructure.basic.file.FileTestConstant.fullChar;
import static com.liuzhilong.infrastructure.basic.file.FileTestConstant.*;

/**
 * 文件随机读写
 */
public class FileRandomAccessIO {
    /**
     * 使用jdk的{@link RandomAccessFile}进行文件的随机读
     * @param file
     */
    public static void randomAccessFileR(File file) throws IOException {

        long start = System.currentTimeMillis();
        System.out.println("开始随机读:"+start);
        Random random = new Random();
        RandomAccessFile randomAccessFile = new RandomAccessFile(file,"rw");
        byte[] data = new byte[fullCharByteLength];
        for (int i = 0; i < loopCount; i++) {
            //计算位置
            int pisItem  =random.nextInt((int) loopCount);
            int pis = pisItem * fullCharByteLength;
            randomAccessFile.seek(pis);
            randomAccessFile.read(data);
        }
        randomAccessFile.close();
        System.out.println("结束随机读:"+System.currentTimeMillis()+",耗时"+(System.currentTimeMillis()-start));


    }

    /**
     * 使用Nio channel 进行读
     * @param file
     */
    public static void channelFileR(File file) throws IOException {

        long start = System.currentTimeMillis();
        System.out.println("开始随机读:"+start);
        Random random = new Random();
        RandomAccessFile randomAccessFile = new RandomAccessFile(file,"rw");
        FileChannel fileChannel = randomAccessFile.getChannel();
        MappedByteBuffer mappedByteBuffer= fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, file.length());
        //分配一个byteBuffer 读取fullCharByteLength个字节
        ByteBuffer byteBuffer = ByteBuffer.allocate(fullCharByteLength);
        for (int i = 0; i < loopCount; i++) {
            //计算位置
            int pisItem  =random.nextInt((int) loopCount);
            int pis = pisItem * fullCharByteLength;
            fileChannel.position(pis);
            byteBuffer.clear();
            fileChannel.read(byteBuffer);
        }
        fileChannel.close();
        System.out.println("结束随机读:"+System.currentTimeMillis()+",耗时"+(System.currentTimeMillis()-start));


    }
    /**
     * 使用Nio MappedByteBuffer 进行读
     * @param file
     */
    public static void mappedByteBufferFileR(File file) throws IOException {

        long start = System.currentTimeMillis();
        System.out.println("开始随机读:"+start);
        Random random = new Random();
        RandomAccessFile randomAccessFile = new RandomAccessFile(file,"rw");
        FileChannel fileChannel = randomAccessFile.getChannel();
        MappedByteBuffer mappedByteBuffer= fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, file.length());
        byte[] data = new byte[fullCharByteLength];
        for (int i = 0; i < loopCount; i++) {
            //计算位置
            int pisItem  =random.nextInt((int) loopCount);
            int pis = pisItem * fullCharByteLength;
            mappedByteBuffer.position(pis);
            mappedByteBuffer.get(data);
        }
        fileChannel.close();
        System.out.println("结束随机读:"+System.currentTimeMillis()+",耗时"+(System.currentTimeMillis()-start));
    }

    /**
     * 使用jdk的{@link RandomAccessFile}进行文件的随机写
     * @param file
     */
    public static void randomAccessFileW(File file) throws IOException {

        long start = System.currentTimeMillis();
        System.out.println("开始随机写:"+start);
        Random random = new Random();
        RandomAccessFile randomAccessFile = new RandomAccessFile(file,"rw");
        byte[] data = replaceChar.getBytes(StandardCharsets.UTF_8);
        for (int i = 0; i < loopCount; i++) {
            //计算位置
            int pisItem  =random.nextInt((int) loopCount);
            int pis = pisItem * fullCharByteLength;
            randomAccessFile.seek(pis);
            randomAccessFile.write(data);
        }
        randomAccessFile.close();
        System.out.println("结束随机写:"+System.currentTimeMillis()+",耗时"+(System.currentTimeMillis()-start));


    }

    /**
     * 使用Nio channel 进行写
     * @param file
     */
    public static void channelFileW(File file) throws IOException {

        long start = System.currentTimeMillis();
        System.out.println("开始随机写:"+start);
        Random random = new Random();
        RandomAccessFile randomAccessFile = new RandomAccessFile(file,"rw");
        FileChannel fileChannel = randomAccessFile.getChannel();
        //分配一个byteBuffer 读取fullCharByteLength个字节
        ByteBuffer byteBuffer = ByteBuffer.allocate(fullCharByteLength);
        byte[] data = replaceChar.getBytes(StandardCharsets.UTF_8);

        for (int i = 0; i < loopCount; i++) {
            //计算位置
            int pisItem  =random.nextInt((int) loopCount);
            int pis = pisItem * fullCharByteLength;
            fileChannel.position(pis);
            byteBuffer.clear();
            byteBuffer.put(data);
            byteBuffer.flip();
            fileChannel.write(byteBuffer);
        }
        fileChannel.close();
        System.out.println("结束随机写:"+System.currentTimeMillis()+",耗时"+(System.currentTimeMillis()-start));


    }
    /**
     * 使用Nio MappedByteBuffer 进行写
     * @param file
     */
    public static void mappedByteBufferFileW(File file) throws IOException {

        long start = System.currentTimeMillis();
        System.out.println("开始随机写:"+start);
        Random random = new Random();
        RandomAccessFile randomAccessFile = new RandomAccessFile(file,"rw");
        FileChannel fileChannel = randomAccessFile.getChannel();
        MappedByteBuffer mappedByteBuffer= fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, file.length());
        byte[] data = replaceChar.getBytes(StandardCharsets.UTF_8);
        for (int i = 0; i < loopCount; i++) {
            //计算位置
            int pisItem  =random.nextInt((int) loopCount);
            int pis = pisItem * fullCharByteLength;
            mappedByteBuffer.position(pis);
            mappedByteBuffer.put(data);
        }
        fileChannel.close();
        System.out.println("结束随机写:"+System.currentTimeMillis()+",耗时"+(System.currentTimeMillis()-start));
    }

    public static void main(String[] args) throws IOException {
        File file = FileSimpleIO.createFile("test" + System.currentTimeMillis() + "1");
        FileSimpleIO.writeByChannel(file);
        mappedByteBufferFileW(file);
    }


}
